package ee.ut.math.chess.game.model;

import java.util.ArrayList;
import java.util.List;

import ee.ut.math.chess.base.model.Board;
import ee.ut.math.chess.base.model.Move;
import ee.ut.math.chess.base.model.Position;
import ee.ut.math.chess.base.model.chesspiece.ChessPiece;
import ee.ut.math.chess.base.model.chesspiece.Color;
import ee.ut.math.chess.base.model.chesspiece.King;
import ee.ut.math.chess.base.model.chesspiece.Pawn;
import ee.ut.math.chess.base.model.chesspiece.Queen;
import ee.ut.math.chess.base.model.chesspiece.Rook;
import ee.ut.math.chess.base.model.exception.GameLogicException;

public class GameLogic {
    private static Position findKing(Color color, Board board) {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                ChessPiece chessPiece = board.getChessPiece(i, j);
                if (chessPiece != null && chessPiece instanceof King && chessPiece.getColor() == color) {
                    return new Position(i, j);
                }
            }
        }
        return null;
    }

    public static Move positionIsThreatenedBy(Position position, Color byColor, Game game) {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                ChessPiece chessPiece = game.getBoard().getChessPiece(i, j);
                if (chessPiece != null && chessPiece.getColor() == byColor) {
                    List<Move> moves = chessPiece.getLegalMoves(i, j, game, true);
                    Move threateningMove = new Move(i, j, position.getX(), position.getY());
                    if (moves.contains(threateningMove)) {
                        return threateningMove;
                    }
                }
            }
        }
        return null;
    }
    public static List<Move> positionIsProtectedBy(Position position, Color byColor, Game game) {
        List<Move> protMoves = new ArrayList<Move>();
    	for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                ChessPiece chessPiece = game.getBoard().getChessPiece(i, j);
                if (chessPiece != null && chessPiece.getColor() == byColor) {
                    List<Move> moves = chessPiece.getLegalMoves(i, j, game, true);
                    Move protectiveMove = new Move(i, j, position.getX(), position.getY());
                    if (moves.contains(protectiveMove)) {
                        protMoves.add(protectiveMove);
                    }
                }
            }
        }
    	if(protMoves.size() == 0){
            return null;
    	}
    	return protMoves;
    }

    public static Move kingIsThreatened(Color color, Game game) {
        Position position = GameLogic.findKing(color, game.getBoard());
        return positionIsThreatenedBy(position, color.getOpposite(), game);
    }
    public static Position kingsPosition(Color color, Game game) {
        Position position = GameLogic.findKing(color, game.getBoard());
        return position;
    }

    public static void setGameStatus(Game game) {
        boolean checkmateNotPossible = checkmateNotPossible(game);
        if (checkmateNotPossible) {
            game.setGameStatus(GameStatus.TIE); // only possible outcome is
                                                // stalemate
            return;
        }

        Move threateningMove = kingIsThreatened(game.getWaitingForPlayer(), game);
        game.setCheckMove(threateningMove);

        Move legalMove = getLegalMove(game);
        if (legalMove != null) {
            if (threateningMove != null) {
                game.setGameStatus(GameStatus.CHECK);
                return;
            }
            game.setGameStatus(GameStatus.ONGOING);
            return;
        }

        if (threateningMove != null) {
            game.setGameStatus(GameStatus.CHECKMATE);
            return;
        }
        game.setGameStatus(GameStatus.STALEMATE);
        return;
    }

    public static Move getLegalMove(Game game) {
        DummyPersistenceManager manager = new DummyPersistenceManager(game);
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                ChessPiece chessPiece = game.getBoard().getChessPiece(i, j);
                if (chessPiece != null && chessPiece.getColor() == game.getWaitingForPlayer()) {
                    List<Move> potentialLegalMoves = chessPiece.getLegalMoves(i, j, game, false);
                    for (Move move : potentialLegalMoves) {
                        try {
                            game.moveInternal(chessPiece, move);
                            manager.rollback(); // opponent has a valid move
                            return move;
                        } catch (GameLogicException e) { // move puts king into
                                                         // check
                            continue;
                        }
                    }
                }
            }
        }
        return null;
    }

    public static boolean checkmateNotPossible(Game game) {
        int whitePieceCount = 0;
        int blackPieceCount = 0;
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                ChessPiece chessPiece = game.getBoard().getChessPiece(i, j);
                if (chessPiece == null) {
                    continue;
                }
                if (chessPiece instanceof Queen || chessPiece instanceof Rook || chessPiece instanceof Pawn) {
                    return false;
                }
                if (chessPiece.getColor() == Color.BLACK) {
                    blackPieceCount++;
                } else {
                    whitePieceCount++;
                }
                if (whitePieceCount > 2 || blackPieceCount > 2) {
                    return false;
                }
            }
        }
        return true;

    }
}
